﻿using System;

namespace DimensionsHelper.Common.Contracts.Metadata;

/// <summary>
///     属性值的数据类型
/// </summary>
public enum PropertyValueType
{
    Null = 0,
    Int = 3,
    Double = 5,
    Bool = 11,
    String = 8,
    Properties = 9
}


/// <summary>
///     此接口表示MDMDocument中通过 [] 定义的附加属性，必须有一个名称和一个值，在xml中tag为property。
/// </summary>
public interface IProperty : IMetadataContextObject, IEquatable<IProperty>
{
    /// <summary>
    ///     获取当前属性值，默认值是 null。
    /// </summary>
    object? Value { get; }

    /// <summary>
    ///     当前属性的数据类型。
    /// </summary>
    PropertyValueType ValueType { get; }

    /// <summary>
    ///     属性所属的数据源。
    /// </summary>
    IDataSource? DataSource { get; }

    /// <summary>
    ///     配置当前属性值为给定整型值。
    /// </summary>
    /// <param name="value">新的属性值</param>
    void SetValue(int value);

    /// <summary>
    ///     配置当前属性值为给定字符串，如果给定值是null，将设置为null。
    /// </summary>
    /// <param name="value">新的属性值</param>
    void SetValue(string? value);

    /// <summary>
    ///     配置当前属性为布尔值。
    /// </summary>
    /// <param name="value">新的属性值</param>
    void SetValue(bool value);

    /// <summary>
    ///     配置当前属性为双精度浮点数值。
    /// </summary>
    /// <param name="value">新的属性值</param>
    void SetValue(double value);

    /// <summary>
    ///     配置当前属性值是属性列表，并将给定属性添加到集合中。
    /// </summary>
    /// <param name="property">给定属性对象</param>
    void SetValue(IProperty property);

    /// <summary>
    ///     配置当前属性是属性列表。
    /// </summary>
    /// <param name="properties">给定属性列表</param>
    void SetValue(IProperties properties);

    /// <summary>
    ///     获取指定类型的属性值，如果类型不符合，返回<paramref name="defaultValue" />。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    T? GetValue<T>(T defaultValue);

    /// <summary>
    ///     获取指定类型的值。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    T? GetValue<T>();
}

/// <summary>
///     元数据附加属性集合，使用 [] 定义，在xml中tag为properties
/// </summary>
public interface IProperties : IMetadataContextCollection<IProperty>
{
    /// <summary>
    ///     不受版本变化影响的属性列表。
    /// </summary>
    IProperties? Unversioned { get; }

    /// <summary>
    ///     设置指定上下文类型下指定名称属性的值。
    /// </summary>
    /// <param name="context">上下文类型</param>
    /// <param name="propertyName">属性名，不区分大小写</param>
    /// <param name="value">属性字符串值，可以是null</param>
    void SetPropertyValue(string context, string propertyName, string value);


    /// <summary>
    ///     设置指定上下文类型下指定名称属性的值。
    /// </summary>
    /// <param name="context">上下文类型</param>
    /// <param name="propertyName">属性名，不区分大小写</param>
    /// <param name="value">属性整数值，不能是null</param>
    void SetPropertyValue(string context, string propertyName, int value);


    /// <summary>
    ///     设置指定上下文类型下指定名称属性的值。
    /// </summary>
    /// <param name="context">上下文类型</param>
    /// <param name="propertyName">属性名，不区分大小写</param>
    /// <param name="value">属性浮点数值，不能是null</param>
    void SetPropertyValue(string context, string propertyName, double value);


    /// <summary>
    ///     设置指定上下文类型下指定名称属性的值。
    /// </summary>
    /// <param name="context">上下文类型</param>
    /// <param name="propertyName">属性名，不区分大小写</param>
    /// <param name="value">属性布尔值，不能是null</param>
    void SetPropertyValue(string context, string propertyName, bool value);


    /// <summary>
    ///     获取指定上下文类型下指定名称属性的值，并转换成给定类型。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="context">上下文类型</param>
    /// <param name="propertyName">属性名，不区分大小写</param>
    /// <param name="defaultValue">转换失败或者属性值是null时返回的值</param>
    /// <returns></returns>
    T? GetPropertyValue<T>(string context, string propertyName, T defaultValue);

    /// <summary>
    ///     获取指定上下文类型下指定名称属性的值，并转换成给定类型。
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="context">上下文类型</param>
    /// <param name="propertyName">属性名，不区分大小写</param>
    /// <returns></returns>
    T? GetPropertyValue<T>(string context, string propertyName);
}


/// <summary>
///     MDM文档中的单行注释
/// </summary>
public interface INote : IMetadataContextObject
{
    /// <summary>
    ///     注释文本内容。
    /// </summary>
    string Value { get; set; }
}


/// <summary>
///     MDM文档中的多行注释
/// </summary>
public interface INotes : IMetadataContextCollection<INote>
{
    /// <summary>
    ///     向注释集合中添加新的单行注释。
    /// </summary>
    /// <param name="value">单行注释内容</param>
    /// <param name="context">注释所处上下文类型</param>
    void Add(string value, string context);

    /// <summary>
    ///     向注释集合中添加指定名称、文本和上下文类型的单行注释。
    /// </summary>
    /// <param name="name">注释名，如果此参数是空字符串，将自动命名</param>
    /// <param name="value">注释文本</param>
    /// <param name="context">注释所在上下文类型</param>
    void Add(string name, string value, string context);

    /// <summary>
    ///     获取下一个有效的注释对象名。
    /// </summary>
    /// <returns></returns>
    string MakeName();
}